import os
import json
import sys
import time
import getpass
username = getpass.getuser()
if username == "root":
    use_paramiko = False
else:
    try:
        import paramiko
        use_paramiko = True
    except Exception as e:
        print(e)
        use_paramiko = False
# python version
import sys
print(sys.version)

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        print("Function {} took {:.6f} seconds to execute.".format(func.__name__, end_time - start_time))
        return result
    return wrapper

@timer
def getUsers():
    users=[]
    with open("/etc/passwd") as fr:
        all_line = fr.readlines()
    for line in all_line:
        user=line.split(":")[0]
        uid=line.split(":")[2]
        gid=line.split(":")[3]
        shell=line.split(":")[6].split("\n")[0]
        if int(uid) >= 1000 and "nologin" not in shell:
            # print(user, uid, gid, shell)
            users.append(user)
    return users

@timer
def getWeakPasswd():
    weakPasswd = []
    with open("weak_passwd.txt") as fr:
        all_line=fr.readlines()
    for line in all_line:
        weakPasswd += [x for x in line.split("\n")[0].split(" ") if len(x) > 0 ]
    weakPasswd = list(set(weakPasswd))
    return weakPasswd

@timer
def getWeakPasswdByuser(user):
    UserWeakPasswd = []
    UserWeakPasswd.append(user)
    for x in [1,2,3,12,123,23]:
        UserWeakPasswd.append(user+str(x))
        UserWeakPasswd.append(user+"@"+str(x))
        UserWeakPasswd.append(user+"-"+str(x))
        UserWeakPasswd.append(user+"_"+str(x))
        UserWeakPasswd.append(user+"."+str(x))
        UserWeakPasswd.append(str(x)+user)
        UserWeakPasswd.append(str(x)+user+"!")
        UserWeakPasswd.append(str(x)+user+"#")
        UserWeakPasswd.append(str(x)+user+"@")
    UserWeakPasswd = list(set(UserWeakPasswd))
    return UserWeakPasswd

class myFile():
    def __init__(self, filepath):
        self._path = filepath
        if os.path.exists(self._path):
            with open(self._path) as f:
                self._data = f.read().split("\n")
        else:
            self._data = []

    def add(self,line):
        with open(self._path, 'a') as f:
            f.write(line)
            f.write("\n")
        self._data.append(line)

    def exists(self,line):
        return line in self._data

@timer
def trypasswd(IP,Port,user,pwd):
    if use_paramiko:
        return trypasswdby_paramiko(IP, Port, user, pwd)
    else:
        return trypasswdby_cmd(IP, Port, user, pwd)

def trypasswdby_paramiko(IP, Port, user, pwd):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(hostname=IP,port=int(Port), username=user, password=pwd)
        ssh.close()
        return True
    except Exception as e:
        ssh.close()
        print(e)
        return False

def trypasswdby_cmd(IP, Port, user, pwd):
    return trypasswdby_cmdv1(IP, Port, user, pwd)

def trypasswdby_cmdv1(IP, Port, user, pwd):
    cmd = 'sshpass -p '+str(pwd)+' ssh -p '+str(Port)+' -o StrictHostKeyChecking=no '+str(user)+'@'+str(IP)+' exit' 
    # 以下表达式只支持 python3.6及以上
    # cmd = f'sshpass -p {pwd} ssh -p {Port} -o StrictHostKeyChecking=no {user}@{IP} exit' 
    exit_code = os.system(cmd)
    return exit_code == 0     

def main():
    servers=["127.0.0.1:22"]
    users=getUsers()
    weakPasswds=getWeakPasswd()
    Frecord = myFile("out_record.txt")
    Fuser = myFile("out_user.txt")
    Fuserpasswd = myFile("out_userpasswd.txt")
    print("server:",servers)
    print("users:",users)
    print("weakPasswd:",weakPasswds)
    for server in servers:
        IP = server.split(":")[0]
        Port = server.split(":")[1]
        for user in users:
            if Fuser.exists(user):
                continue
            UserWeakPasswd = getWeakPasswdByuser(user)
            UserWeakPasswd = UserWeakPasswd + weakPasswds
            UserWeakPasswd = list(set(UserWeakPasswd))
            for pwd in UserWeakPasswd:
                _red = IP+","+Port+","+user+","+pwd
                if Frecord.exists(_red):
                    continue
                if trypasswd(IP, Port, user, pwd):
                    Fuserpasswd.add(_red)  
                    Frecord.add(_red)
                    break
                else:              
                    Frecord.add(_red)
            Fuser.add(user)
    
if __name__=="__main__":
    main()